﻿#pragma once

#include <learn/ais/ais_msg.h>

namespace xi
{

namespace ais
{

class EXT_SYMBOL AIS_Object
{
  public:
    enum Status
    {
        Normal,
        Hovered,
        Pressed,
        Hidden,
        Dead
    };

    enum ShadeMode
    {
        Shade,
        Wire,
        Zebra,
        Curvature
    };

    AIS_Object(AIS_Object &&) = delete;

    /**
     * @brief 默认构造函数
     *
     */
    explicit AIS_Object() = default;

    /**
     * @brief 析构函数
     *
     */
    virtual ~AIS_Object() = default;

    /**
     * @brief 获得状态
     *
     * @return Status
     */
    Status status() const;

    /**
     * @brief 获得渲染模式
     *
     * @return ShadeMode
     */
    ShadeMode shade_mode() const;

    /**
     * @brief 获得渲染器
     *
     * @return std::shared_ptr<AIS_Renderer>
     */
    std::shared_ptr<AIS_Renderer> renderer() const;

    /**
     * @brief 设置状态
     *
     * @param[in] status
     */
    void set_status(Status status);

    /**
     * @brief 设置渲染模式
     *
     * @param[in] mode
     */
    void set_shade_mode(ShadeMode mode);

    /**
     * @brief 设置父对象
     *
     * @param[in] parent
     */
    void set_parent(AIS_Object *parent);

    /**
     * @brief 添加子对象
     *
     * @param[in] child
     */
    void add_child(std::shared_ptr<AIS_Object> child);

    /**
     * @brief 消息处理函数
     *
     * @param[in] msg
     */
    void handle_msg(std::shared_ptr<AIS_Msg> msg);

    /**
     * @brief 访问接口
     *
     * @param[in] msg
     */
    virtual void visit(AIS_InitMsg *msg);
    virtual void visit(AIS_UpdateMsg *msg);
    virtual void visit(AIS_PaintMsg *msg);
    virtual void visit(AIS_ShowMsg *msg);
    virtual void visit(AIS_MoveMsg *msg);
    virtual void visit(AIS_MouseMsg *msg);
    virtual void visit(AIS_DestroyMsg *msg);

  protected:
    AIS_Object *m_parent{nullptr}; // 反向指针，不要使用智能指针
    Status m_status{Normal};
    ShadeMode m_shadeMode{Shade};
    std::function<bool(AIS_MouseMsg *)> m_collisionFunc{nullptr};
    std::vector<std::shared_ptr<AIS_Object>> m_children;
    std::shared_ptr<AIS_Renderer> m_renderer;
};

template <class Derived> inline void AIS_MsgImpl<Derived>::accept(AIS_Object *visitor)
{
    // 静态判断，要求继承关系，节省运行时开销
    static_assert(std::is_base_of<AIS_MsgImpl, Derived>::value, "Derived must be a Msg");
    visitor->visit(static_cast<Derived *>(this));
}

} // namespace ais

} // namespace xi
